package com.bsdsma.visonManagementSystemapp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bsdsma.visonManagementSystemapp.constants.ErrorCodes;
import com.bsdsma.visonManagementSystemapp.dto.*;
import com.bsdsma.visonManagementSystemapp.entity.Gonggao;
import com.bsdsma.visonManagementSystemapp.entity.School;
import com.bsdsma.visonManagementSystemapp.entity.User;
import com.bsdsma.visonManagementSystemapp.entity.Student;
import com.bsdsma.visonManagementSystemapp.entity.Teacher;
import com.bsdsma.visonManagementSystemapp.entity.Admin;
import com.bsdsma.visonManagementSystemapp.exceptionhandler.GlobalRuntimeException;
import com.bsdsma.visonManagementSystemapp.mapper.GonggaoMapper;
import com.bsdsma.visonManagementSystemapp.service.GonggaoService;
import com.bsdsma.visonManagementSystemapp.service.SchoolService;
import com.bsdsma.visonManagementSystemapp.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Collections;

@Slf4j
@Service
public class GonggaoServiceImpl implements GonggaoService {

    /**
     * 使用Spring注入Mybatis操作对象
     */
    @Autowired
    private GonggaoMapper mapper;
    @Lazy
    @Autowired
    private SchoolService schoolService;

    @Override
    public PageRetDto<Gonggao> search(GonggaoSearchDto dto) {
        // Get current user from LocalUtils
        User currentUser = LocalUtils.getUser();
        if (currentUser == null) {
            throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "请先登录");
        }

        // Get user's school based on role
        final School xuexiao;
        if (currentUser instanceof Student) {
            xuexiao = ((Student) currentUser).getXuexiao();
        } else if (currentUser instanceof Teacher) {
            xuexiao = ((Teacher) currentUser).getXuexiao();
        } else if (currentUser instanceof Admin) {
            // Admin can access all announcements, no need to set xuexiao
            xuexiao = null;
        } else {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "无效的用户类型");
        }

        // For students and teachers, only show announcements from their school
        if ((currentUser instanceof Student || currentUser instanceof Teacher) && xuexiao != null) {
            dto.setXuexiao(xuexiao.getName());
        }

        // Role-based filtering
        QueryWrapper<Gonggao> wrapper = new QueryWrapper<>();
        wrapper.eq("g.status", 0);

        // For students and teachers, only show announcements from their school
        if ((currentUser instanceof Student || currentUser instanceof Teacher) && xuexiao != null) {
            wrapper.eq("g.xuexiao_id", xuexiao.getId());
        }
        // For admin role, no additional filtering needed - they can see all announcements

        // Add search criteria
        if (!StringUtils.isBlank(dto.getTitle())) {
            wrapper.like("g.title", "%" + dto.getTitle() + "%");
        }
        if (!StringUtils.isBlank(dto.getXuexiao())) {
            // For admin users, find the school by name
            if (currentUser instanceof Admin) {
                School searchSchool = schoolService.findByName(dto.getXuexiao());
                if (searchSchool != null) {
                    wrapper.eq("g.xuexiao_id", searchSchool.getId());
                } else {
                    // Return empty result if school not found
                    return new PageRetDto<>();
                }
            } else if (xuexiao != null) {
                // For non-admin users, they can only see their own school's announcements
                wrapper.eq("g.xuexiao_id", xuexiao.getId());
            }
        }
        // If xuexiao is null/empty and user is admin, no school filter is applied - will return all schools' announcements

        IPage<Gonggao> pageData = mapper.selectPage(new PageDTO<>(dto.getPage(), dto.getSize()), wrapper);
        return PageRetUtils.parse(pageData);
    }

    @Override
    public List<Gonggao> listAll() {
        return this.listAllWithRet().getList();
    }

    @Override
    public ListAllRetDto<Gonggao> listAllWithRet() {
        Gonggao bean = new Gonggao();
        bean.setStatus(0);
        QueryWrapper<Gonggao> wrapper = new QueryWrapper<>(bean);
        boolean onlyMine = false;

        // Get current user from LocalUtils
        User currentUser = LocalUtils.getUser();
        if (currentUser == null) {
            throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "请先登录");
        }

        // Role-based filtering
        final School xuexiao;
        if (currentUser instanceof Student) {
            xuexiao = ((Student) currentUser).getXuexiao();
        } else if (currentUser instanceof Teacher) {
            xuexiao = ((Teacher) currentUser).getXuexiao();
        } else if (currentUser instanceof Admin) {
            // Admin can access all announcements, no need to set xuexiao
            xuexiao = null;
        } else {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "无效的用户类型");
        }

        if (xuexiao != null) {
            // For students and teachers, only show announcements from their school
            // unless the announcement is for all schools (xuexiao = "全部")
            wrapper.and(w -> w.eq("xuexiao", xuexiao)
                           .or()
                           .eq("xuexiao", "全部"));
        }
        // For admin role, no additional filtering needed - they can see all announcements

        return new ListAllRetDto<>(onlyMine, mapper.selectList(wrapper));
    }

    @Override
    public Gonggao add(GonggaoAddDto dto) {
        // Get current user from LocalUtils
        User currentUser = LocalUtils.getUser();
        if (currentUser == null) {
            throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "请先登录");
        }

        // Handle "全部" case - create announcement for all schools
        if ("全部".equals(dto.getXuexiao())) {
            // Only admin can create announcements for all schools
            if (!(currentUser instanceof Admin)) {
                throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "只有管理员可以为所有学校创建公告");
            }
            
            // Get all active schools
            List<School> allSchools = schoolService.listAll();
            if (allSchools.isEmpty()) {
                throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "没有找到任何学校");
            }
            
            // Create announcement for each school
            Gonggao lastCreated = null;
            for (School school : allSchools) {
                Gonggao bean = new Gonggao();
                bean.setTitle(dto.getTitle());
                bean.setNeirong(dto.getNeirong());
                bean.setXuexiaoId(school.getId());
                bean.setXuexiao(school.getName());
                bean.setStatus(0);
                bean.setCt(DateUtils.getNow());
                bean.setUt(DateUtils.getNow());
                mapper.insert(bean);
                lastCreated = bean;
            }
            return lastCreated; // Return the last created announcement
        }

        // Get user's school based on role
        final School xuexiao;
        if (currentUser instanceof Student) {
            xuexiao = ((Student) currentUser).getXuexiao();
        } else if (currentUser instanceof Teacher) {
            xuexiao = ((Teacher) currentUser).getXuexiao();
        } else if (currentUser instanceof Admin) {
            // Admin can add announcements for any school
            xuexiao = schoolService.findByName(dto.getXuexiao());
            if (xuexiao == null) {
                throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "学校不存在");
            }
        } else {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "无效的用户类型");
        }

        Gonggao bean = new Gonggao();
        bean.setTitle(dto.getTitle());
        bean.setNeirong(dto.getNeirong());
        bean.setXuexiaoId(xuexiao.getId());
        bean.setXuexiao(xuexiao.getName());
        bean.setStatus(0);
        bean.setCt(DateUtils.getNow());
        bean.setUt(DateUtils.getNow());
        mapper.insert(bean);
        return bean;
    }

    @Override
    public Gonggao update(Long id, GonggaoAddDto dto) {
        // Get current user from LocalUtils
        User currentUser = LocalUtils.getUser();
        if (currentUser == null) {
            throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "请先登录");
        }

        // Get user's school based on role
        final School xuexiao;
        if (currentUser instanceof Student) {
            xuexiao = ((Student) currentUser).getXuexiao();
        } else if (currentUser instanceof Teacher) {
            xuexiao = ((Teacher) currentUser).getXuexiao();
        } else if (currentUser instanceof Admin) {
            // Admin can update announcements for any school
            xuexiao = schoolService.findByName(dto.getXuexiao());
            if (xuexiao == null) {
                throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "学校不存在");
            }
        } else {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "无效的用户类型");
        }

        Gonggao bean = mapper.selectById(id);
        if (bean == null) {
            throw new GlobalRuntimeException(ErrorCodes.OBJ_NOT_EXISTS, "公告不存在");
        }

        // Only allow updating announcements from the same school (except for admin)
        if (!(currentUser instanceof Admin) && xuexiao.getId() != bean.getXuexiaoId()) {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "只能修改本校公告");
        }

        bean.setTitle(dto.getTitle());
        bean.setNeirong(dto.getNeirong());
        // For admin, update the school ID based on the school name
        if (currentUser instanceof Admin) {
            bean.setXuexiaoId(xuexiao.getId());
        }
        bean.setUt(DateUtils.getNow());
        mapper.updateById(bean);
        return bean;
    }

    @Override
    public Gonggao getById(Long id) {
        return mapper.selectById(id);
    }

    @Override
    public void delete(Long id) {
        // Get current user from LocalUtils
        User currentUser = LocalUtils.getUser();
        if (currentUser == null) {
            throw new GlobalRuntimeException(ErrorCodes.PARAMS_ERROR, "请先登录");
        }

        // Get user's school based on role
        final School xuexiao;
        if (currentUser instanceof Student) {
            xuexiao = ((Student) currentUser).getXuexiao();
        } else if (currentUser instanceof Teacher) {
            xuexiao = ((Teacher) currentUser).getXuexiao();
        } else if (currentUser instanceof Admin) {
            // Admin can delete announcements from any school
            xuexiao = null;
        } else {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "无效的用户类型");
        }

        Gonggao bean = mapper.selectById(id);
        if (bean == null) {
            throw new GlobalRuntimeException(ErrorCodes.OBJ_NOT_EXISTS, "公告不存在");
        }

        // Only allow deleting announcements from the same school (except for admin)
        if (!(currentUser instanceof Admin) && xuexiao.getId() != bean.getXuexiaoId()) {
            throw new GlobalRuntimeException(ErrorCodes.PERMISSION_ERROR, "只能删除本校公告");
        }

        bean.setStatus(-1);
        bean.setUt(DateUtils.getNow());
        mapper.updateById(bean);
    }

    @Override
    public int updateById(Gonggao bean) {
        return mapper.updateById(bean);
    }

    @Override
    public Long count() {
        Gonggao bean = new Gonggao();
        bean.setStatus(0);
        return mapper.selectCount(new QueryWrapper<>(bean));
    }

    @Override
    public List<DataGroupByDateDto> countByDay(Date beginDate, Date endDate) {
        return mapper.countByDay(beginDate, endDate);
    }
}
